package com.ruoyi.business.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


import org.apache.commons.lang3.StringUtils;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.business.dao.SysRegionDao;
import com.ruoyi.business.domain.Region;
import com.ruoyi.business.service.ISysRegionService;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 * sys_regionService业务层处理
 *
 * @author liutietou
 * @since 1.0 2025-07-20
 */
@Transactional(readOnly = true)
@Service
public class SysRegionServiceImpl implements ISysRegionService {

    @Autowired
    private SysRegionDao sysRegionDao;
     @Autowired
    public RedisTemplate redisTemplate;
    private static final String REGION_LIST_KEY = "sys:region:list";
    /**
     * 查询sys_region
     *
     * @param id sys_regionID
     * @return sys_region
     */
    @Override
    public Region findById(Long id) {
        return sysRegionDao.findById(id).get();
    }

    /**
     * 分页查询sys_region列表
     *
     * @param req sys_region
     * @return sys_region
     */
    @Override
    public Page<Region> findSysRegionPage(Region req) {
        Specification<Region> example = formatQueryParams(req);
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Pageable pageable = PageRequest.of(pageDomain.getPageNo(),
                Optional.ofNullable(pageDomain.getPageSize()).orElse(PageDomain.DEFAULT_PAGE_SIZE),
                Sort.Direction.ASC,
                Optional.ofNullable(pageDomain.getOrderByColumn()).orElse("code"));
        Page<Region> page = sysRegionDao.findAll(example, pageable);
        return page;
    }

    /**
     * 分页查询sys_region列表
     *
     * @param req sys_region
     * @return sys_region
     */
    @Override
    public List<Region> findSysRegionTree(Region req) {
        List<Region> regionList = (List<Region>) redisTemplate.opsForValue().get(REGION_LIST_KEY);
        if (regionList != null) {
            return regionList;
        }
        // 2. redis没有，查数据库
        regionList =findSysRegionList(req,""); // 你自己的查询方法
        // 3. 写入redis
        redisTemplate.opsForValue().set(REGION_LIST_KEY, regionList);
         return  regionList ;
    }



    private  List<Region> findSysRegionList(Region req,String parentFullname) {
        Specification<Region> example = formatQueryParams(req);
        List<Region> list = sysRegionDao.findAll(example, Sort.by(Sort.Direction.ASC,"code"));
        for(Region  region:list){
            Region  dto=new Region();
            dto.setParentCode(region.getCode());
            if(region.getLevel()==1){
                region.setFullname(region.getName());
            }else {
                region.setFullname(parentFullname+"|"+region.getName());
            }
            if(region.getLevel()==4){
                continue;
            }
            List<Region>  childs=findSysRegionList(dto,region.getFullname());
            region.setChildren(childs);
        }
        return list;
    }


    private Specification<Region> formatQueryParams(Region req){
        Specification<Region> example = new Specification<Region>() {
            private static final long serialVersionUID = 1L;

            @Override
            public Predicate toPredicate(Root<Region> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<>();
                if (null != req.getId()){
                    Predicate pre = cb.equal(root.get("id").as(Long.class), req.getId());
                    list.add(pre);
                }
                if (StringUtils.isNotBlank(req.getCode())){
                    Predicate pre = cb.equal(root.get("code").as(String.class), req.getCode());
                    list.add(pre);
                }
                if (StringUtils.isNotBlank(req.getName())){
                    Predicate pre = cb.like(root.get("name").as(String.class), "%" + req.getName()+ "%");
                    list.add(pre);
                }
                if (null != req.getLevel()&& req.getLevel()>0){
                    Predicate pre = cb.equal(root.get("level").as(Integer.class), req.getLevel());
                    list.add(pre);
                }
                if (StringUtils.isNotBlank(req.getParentCode())){
                    Predicate pre = cb.equal(root.get("parentCode").as(String.class), req.getParentCode());
                    list.add(pre);
                }
                if (list.isEmpty()) {
                    return null;
                }
                return cb.and(list.toArray(new Predicate[0]));
            }
        };
        return example;
    }

    /**
     * 保存（新增/修改）sys_region
     *
     * @param region sys_region
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(Region region) {
        sysRegionDao.save(region);
    }


    /**
     * 批量删除sys_region
     *
     * @param ids 需要删除的sys_regionID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByIds(List<Long> ids) {
        List<Region> existBeans = sysRegionDao.findAllById(ids);
        if(!existBeans.isEmpty()){
            sysRegionDao.deleteAll(existBeans);
        }
    }

    /**
     * 删除sys_region信息
     *
     * @param id sys_regionID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteSysRegionById(Long id) {
         sysRegionDao.deleteById(id);
    }
}
